using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;

namespace Catastrophe.Common.ObjM
{
	public class ReflectionUtil
	{
		public static Dictionary<string, Assembly> GetAssembly(params string[] assemblyStrBuffer)
		{
			try
			{
				Dictionary<string, Assembly> dictionary = new Dictionary<string, Assembly>();
				foreach (string text in assemblyStrBuffer)
				{
					if (string.IsNullOrWhiteSpace(text))
					{
						continue;
					}
					string text2 = text.ToLower();
					Assembly assembly = null;
					if (text2.EndsWith(".dll") || text2.EndsWith(".exe"))
					{
						string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, text);
						if (File.Exists(path))
						{
							assembly = Assembly.LoadFrom(text);
						}
					}
					else
					{
						assembly = Assembly.Load(text);
					}
					if (!(assembly == null))
					{
						string name = assembly.GetName().Name;
						if (!dictionary.Keys.Contains(name))
						{
							dictionary.Add(name, assembly);
						}
					}
				}
				return dictionary;
			}
			catch (Exception ex)
			{
				throw ex;
			}
		}

		public static T CreateInstance<T>(string assemblyInfo, string fullClassName) where T : class
		{
			Assembly assembly = Assembly.Load(assemblyInfo);
			return assembly.CreateInstance(fullClassName) as T;
		}

		public static object CreateInstance(string assemblyInfo, string fullClassName)
		{
			return Assembly.Load(assemblyInfo).CreateInstance(fullClassName);
		}

		public static object CreateInstance(Assembly assembly, string fullClassName)
		{
			return assembly.CreateInstance(fullClassName);
		}

		public static object ExcuteMethod(string assemblyInfo, string fullClassName, string methodName, object[] param = null)
		{
			Type type = Assembly.Load(assemblyInfo)?.GetType(fullClassName);
			return (type?.GetMethod(methodName))?.Invoke(Activator.CreateInstance(type), param);
		}

		public static object ExcuteMethod(Type classType, MethodInfo methodInfo, object[] param = null)
		{
			return methodInfo?.Invoke(Activator.CreateInstance(classType), param);
		}

		public static Tuple<Type, MethodInfo> GetMethodInfo(string assemblyInfo, string fullClassName, string methodName, Type[] paramTypeAry = null)
		{
			Stopwatch stopwatch = new Stopwatch();
			stopwatch.Start();
			Type type = Assembly.Load(assemblyInfo)?.GetType(fullClassName);
			MethodInfo item = ((paramTypeAry != null) ? type?.GetMethod(methodName, paramTypeAry) : type?.GetMethod(methodName));
			stopwatch.Stop();
			long elapsedMilliseconds = stopwatch.ElapsedMilliseconds;
			return new Tuple<Type, MethodInfo>(type, item);
		}

		public static object ExcuteMethod(Assembly assembly, string fullClassName, string methodName, object[] param = null)
		{
			Type type = assembly?.GetType(fullClassName);
			return (type?.GetMethod(methodName))?.Invoke(Activator.CreateInstance(type), param);
		}

		public static void ExcuteMethod<T>(string methodName)
		{
			Type typeFromHandle = typeof(T);
			(typeFromHandle?.GetMethod(methodName))?.Invoke(Activator.CreateInstance(typeFromHandle), null);
		}

		public static List<T> GetInterfaceSingle<T>(string assemblyInfo) where T : class
		{
			Assembly assembly = Assembly.Load(assemblyInfo);
			if (assembly != null)
			{
				Type[] assemblyTypes = ReflectionUtil.GetAssemblyTypes(assembly);
				if (assemblyTypes != null)
				{
					return (from t in assemblyTypes
						where t.GetInterfaces().Contains(typeof(T))
						select t into x
						select Activator.CreateInstance(x) as T).ToList();
				}
			}
			return new List<T>();
		}

		public static List<T> GetInterfaceMutile<T>(List<string> assemblyBuffer) where T : class
		{
			List<T> list = new List<T>();
			foreach (string item in assemblyBuffer)
			{
				list.AddRange(ReflectionUtil.GetInterfaceSingle<T>(item));
			}
			return list;
		}

		public static List<T> GetInterfaceMutile<T>() where T : class
		{
			return (from x in AppDomain.CurrentDomain.GetAssemblies().SelectMany((Assembly a) => ReflectionUtil.GetAssemblyTypes(a)?.Where((Type t) => t.GetInterfaces().Contains(typeof(T))))
				select Activator.CreateInstance(x) as T).ToList();
		}

		public static Dictionary<string, T> GetInterfaceDicMutile<T>() where T : class
		{
			Dictionary<string, T> dic = new Dictionary<string, T>();
			(from x in AppDomain.CurrentDomain.GetAssemblies().SelectMany((Assembly a) => ReflectionUtil.GetAssemblyTypes(a)?.Where((Type t) => t.GetInterfaces().Contains(typeof(T))))
				select Activator.CreateInstance(x) as T).ToList().ForEach(delegate(T x)
			{
				dic.Add(x.GetType().FullName ?? throw new InvalidOperationException(), x);
			});
			return dic;
		}

		public static Dictionary<string, List<T>> GetInterfaceDicMutile2<T>() where T : class
		{
			List<Assembly> assemblyBuff = AppDomain.CurrentDomain.GetAssemblies().ToList();
			return ReflectionUtil.GetInterfaceDicMutile2<T>(assemblyBuff);
		}

		public static List<Type> GetInterfaceMutile<T>(Assembly[] assemblyBuffer)
		{
			List<Type> list = new List<Type>();
			Dictionary<string, Type> dictionary = new Dictionary<string, Type>();
			foreach (Assembly assembly in assemblyBuffer)
			{
				List<Type> list2 = ReflectionUtil.GetAssemblyTypes(assembly)?.Where((Type t) => t.GetInterfaces().Contains(typeof(T))).ToList();
				if (list2 == null)
				{
					continue;
				}
				foreach (Type item in list2)
				{
					dictionary.Add(assembly.FullName + "." + item.Namespace, item);
				}
				list.AddRange((from t in assembly.GetTypes()
					where t.GetInterfaces().Contains(typeof(T))
					select t).ToList());
			}
			return list;
		}

		public static Dictionary<string, T> GetInterfaceDicMutile<T>(List<string> assemblyBuff) where T : class
		{
			Dictionary<string, T> dictionary = new Dictionary<string, T>();
			foreach (string item in assemblyBuff)
			{
				Assembly assembly = Assembly.Load(item);
				List<Type> list = ReflectionUtil.GetAssemblyTypes(assembly)?.Where((Type t) => t.GetInterfaces().Contains(typeof(T))).ToList();
				if (list == null)
				{
					continue;
				}
				foreach (Type item2 in list)
				{
					T value = Activator.CreateInstance(item2) as T;
					dictionary.Add(item2.FullName ?? "", value);
				}
			}
			return dictionary;
		}

		public static Dictionary<string, T> GetInterfaceDicMutile<T>(List<Assembly> assemblyBuff) where T : class
		{
			Dictionary<string, T> dictionary = new Dictionary<string, T>();
			foreach (Assembly item in assemblyBuff)
			{
				try
				{
					List<Type> list = ReflectionUtil.GetAssemblyTypes(item)?.Where((Type t) => t?.GetInterfaces().Contains(typeof(T)) ?? false).ToList();
					if (list == null)
					{
						continue;
					}
					foreach (Type item2 in list)
					{
						T value = Activator.CreateInstance(item2) as T;
						dictionary.Add(item2.FullName ?? "", value);
					}
				}
				catch (Exception innerException)
				{
					DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(14, 3);
					defaultInterpolatedStringHandler.AppendLiteral("实现接口");
					defaultInterpolatedStringHandler.AppendFormatted(typeof(T));
					defaultInterpolatedStringHandler.AppendLiteral("类查询发生异常");
					defaultInterpolatedStringHandler.AppendFormatted(Environment.NewLine);
					defaultInterpolatedStringHandler.AppendLiteral("程序集");
					defaultInterpolatedStringHandler.AppendFormatted(item.FullName);
					throw new Exception(defaultInterpolatedStringHandler.ToStringAndClear(), innerException);
				}
			}
			return dictionary;
		}

		public static Dictionary<string, List<T>> GetInterfaceDicMutile2<T>(List<Assembly> assemblyBuff) where T : class
		{
			Dictionary<string, List<T>> dictionary = new Dictionary<string, List<T>>();
			foreach (Assembly item2 in assemblyBuff)
			{
				try
				{
					List<Type> list = ReflectionUtil.GetAssemblyTypes(item2)?.Where((Type t) => t?.GetInterfaces().Contains(typeof(T)) ?? false).ToList();
					if (list == null || list.Count == 0)
					{
						continue;
					}
					List<T> list2 = new List<T>();
					foreach (Type item3 in list)
					{
						T item = Activator.CreateInstance(item3) as T;
						list2.Add(item);
					}
					dictionary.Add(item2.GetName().Name, list2);
				}
				catch (Exception innerException)
				{
					DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(14, 3);
					defaultInterpolatedStringHandler.AppendLiteral("实现接口");
					defaultInterpolatedStringHandler.AppendFormatted(typeof(T));
					defaultInterpolatedStringHandler.AppendLiteral("类查询发生异常");
					defaultInterpolatedStringHandler.AppendFormatted(Environment.NewLine);
					defaultInterpolatedStringHandler.AppendLiteral("程序集");
					defaultInterpolatedStringHandler.AppendFormatted(item2.FullName);
					throw new Exception(defaultInterpolatedStringHandler.ToStringAndClear(), innerException);
				}
			}
			return dictionary;
		}

		public static Dictionary<string, Type> GetInterfaceMutile<T>(Dictionary<string, Assembly> assemblyBuffer)
		{
			Dictionary<string, Type> dictionary = new Dictionary<string, Type>();
			foreach (string key in assemblyBuffer.Keys)
			{
				Type[] assemblyTypes = ReflectionUtil.GetAssemblyTypes(assemblyBuffer[key]);
				if (assemblyTypes != null)
				{
					dictionary.Add(key, assemblyTypes.Where((Type t) => t?.GetInterfaces().Contains(typeof(T)) ?? false).ToList().FirstOrDefault());
				}
			}
			return dictionary;
		}

		public static Type[] GetAssemblyTypes(Assembly assembly)
		{
			Type[] array;
			try
			{
				array = assembly?.GetTypes();
			}
			catch (ReflectionTypeLoadException ex)
			{
				array = ex.Types;
			}
			return array?.Where((Type x) => x != null).ToArray();
		}

		public static Dictionary<string, List<Type>> GetAssemblyTypes<T>(int flag = 0, params Assembly[] assemblyBuff)
		{
			if (assemblyBuff == null)
			{
				throw new ArgumentNullException("assemblyBuff");
			}
			Dictionary<string, List<Type>> dictionary = new Dictionary<string, List<Type>>();
			foreach (Assembly assembly in assemblyBuff)
			{
				try
				{
					dictionary.Add(value: flag switch
					{
						0 => assembly?.GetTypes()?.Where((Type x) => x.IsClass && !x.IsAbstract && x.BaseType!.Name == typeof(T).Name).ToList(), 
						1 => assembly?.GetTypes()?.Where((Type x) => x.IsClass && !x.IsAbstract && x.GetInterfaces().Contains(typeof(T))).ToList(), 
						_ => throw new Exception("not support param flag!"), 
					}, key: assembly.GetName().Name);
				}
				catch (Exception innerException)
				{
					DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(14, 3);
					defaultInterpolatedStringHandler.AppendLiteral("实现接口");
					defaultInterpolatedStringHandler.AppendFormatted(typeof(T));
					defaultInterpolatedStringHandler.AppendLiteral("类查询发生异常");
					defaultInterpolatedStringHandler.AppendFormatted(Environment.NewLine);
					defaultInterpolatedStringHandler.AppendLiteral("程序集");
					defaultInterpolatedStringHandler.AppendFormatted(assembly.FullName);
					throw new Exception(defaultInterpolatedStringHandler.ToStringAndClear(), innerException);
				}
			}
			return dictionary;
		}
	}
}
